/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-10-07     huger       the first version
 */

#include "app_io.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#define bool
#include <qled.h>
#undef bool

#ifdef __cplusplus
}
#endif /* __cplusplus */



#define DBG_TAG "io"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

const uint32_t emg_pin[2] = {
        GET_PIN(C, 13),
        GET_PIN(C, 14),
};
const uint32_t rgb_pin[3]={
        GET_PIN(C,0),
        GET_PIN(C,1),
        GET_PIN(C,2),
};
const uint32_t brake_pin = GET_PIN(C,15);

const uint32_t sd_pin = GET_PIN(B, 9);

const uint32_t beep_pin = GET_PIN(D, 2);

const uint32_t key_pin = GET_PIN(A, 4);

static bitfilter_t key_filter;
static bitfilter_t emg_filter[2];

iomap gpio_map;

static void input_fulsh(iomap* map)
{
    int bitval = 0;

    for(uint32_t i = 0 ; i < sizeof(emg_pin) / sizeof(uint32_t); i++)
    {
        bitval = rt_pin_read(emg_pin[i]);
        mod_bitfilter_poll(!bitval, emg_filter + i);

        map->emg_st[i] = !mod_bitfilter_state(emg_filter + i);
    }
    map->emg_st[1] = !map->emg_st[1];

    bitval = rt_pin_read(key_pin);
    mod_bitfilter_poll(!bitval, &key_filter);
    map->key_st[0] = mod_bitfilter_state(&key_filter);
    map->key_st[1] = map->key_st[0];
}

static void output_fulsh(iomap* map)
{
    rt_pin_write(sd_pin, map->sd_st);

    rt_pin_write(brake_pin, map->brake_st);

    if(map->beep_freq != 0 && map->beep_st)
    {
        int ts = 1000 / map->beep_freq / 2;
        qled_set_blink(beep_pin, ts, ts);
    }
    else
    {
        qled_set_off(beep_pin);
    }

    if((map->rgb.style_backup != map->rgb.style)||(map->rgb.freq_backup != map->rgb.freq))
    {
        map->rgb.style_backup = map->rgb.style;
        map->rgb.freq_backup = map->rgb.freq;
        int time = 1000.0f / map->rgb.freq / 2;

        if(map->rgb.style & 0x04){
            qled_set_blink(rgb_pin[2], time, time);
        }
        else
        {
            qled_set_off(rgb_pin[2]);
        }

        if(map->rgb.style & 0x02)
        {
            qled_set_blink(rgb_pin[1], time, time);
        }
        else
        {
            qled_set_off(rgb_pin[1]);
        }

        if(map->rgb.style & 0x01)
        {
            qled_set_blink(rgb_pin[0], time, time);
        }
        else
        {
            qled_set_off(rgb_pin[0]);
        }
    }


}

static void app_io_thread_entry(void* param)
{
    while(1)
    {

        iomap map = {0};

        rt_enter_critical();
        memcpy(&map, param, sizeof(iomap));
        rt_exit_critical();

        input_fulsh(&map);
        output_fulsh(&map);

        rt_enter_critical();
        memcpy(param, &map, sizeof(iomap));
        rt_exit_critical();

        rt_thread_mdelay(10);
    }
}

void app_io_init(void)
{
    uint32_t i;
    iomap* map = &gpio_map;
    //变量初始化
    map->sd_st = 0;
    map->brake_st =0;
    map->beep_st=0;
    map->beep_freq = 0;
    map->rgb.style = 4;map->rgb.freq=1;
    //初始化滤波结构体
    mod_bitfilter_init(&key_filter , 5, 5);

    for(i = 0 ; i < sizeof(emg_filter) / sizeof(bitfilter_t); i++)
        mod_bitfilter_init(emg_filter + i, 5, 5);

    //输入引脚初始化

    rt_pin_mode(key_pin, PIN_MODE_INPUT);

    for(i = 0 ; i < sizeof(emg_pin) / sizeof(uint32_t); i++)
        rt_pin_mode(emg_pin[i], PIN_MODE_INPUT);

    for(int i = 0; i < 30; i++)
    {
        input_fulsh(map);
        rt_thread_mdelay(5);
    }

//    output_fulsh(map);

    //输出引脚初始化
    rt_pin_mode(beep_pin, PIN_MODE_OUTPUT);
    qled_add(beep_pin, 1);
    qled_set_off(beep_pin);

    rt_pin_mode(sd_pin, PIN_MODE_OUTPUT);

    rt_pin_mode(brake_pin, PIN_MODE_OUTPUT);

    for(i = 0 ; i < sizeof(rgb_pin) / sizeof(uint32_t); i++)
    {
        uint32_t* p= (uint32_t*)rgb_pin;
        rt_pin_mode((rt_base_t)p[i], PIN_MODE_OUTPUT);
        qled_add((int)p[i], 1);
        qled_set_off((int)p[i]);
    }

    output_fulsh(map);

    rt_thread_t thread = rt_thread_create("io", app_io_thread_entry, map,
                                  1024, 14, 20);

    if (thread == RT_NULL)
    {
        LOG_D("io_thread error");
    }

    rt_thread_startup(thread);

}

void app_io_get_gpio_map(iomap* map)
{
    rt_enter_critical();
    memcpy(map, &gpio_map, sizeof(iomap));
    rt_exit_critical();
}

void app_io_set_gpio_map(iomap* map)
{
    rt_enter_critical();
    memcpy(&gpio_map, map, sizeof(iomap));
    rt_exit_critical();
}


void app_brake_state_set(uint8_t state)
{
    rt_enter_critical();
    gpio_map.brake_st = state;
    rt_pin_write(brake_pin, gpio_map.brake_st);
    rt_exit_critical();
}

static int dbg_io_info(int argc, char *argv[])
{
    uint32_t i;
//    for(i = 0 ; i < sizeof(gpio_map.hall_st) / sizeof(uint8_t); i++)
//        LOG_I("hall_st[%d] = %d", i, gpio_map.hall_st[i]);
//
//    for(i = 0 ; i < sizeof(gpio_map.key_st) / sizeof(uint8_t); i++)
//        LOG_I("key_st[%d] = %d", i, gpio_map.key_st[i]);
//
//    for(i = 0 ; i < sizeof(gpio_map.sense_st) / sizeof(uint8_t); i++)
//        LOG_I("sense_st[%d] = %d", i, gpio_map.sense_st[i]);
//
//    LOG_I("fan_pow = %d", gpio_map.fan_pow);
    LOG_I("key_st[%d] = %d", 0, gpio_map.key_st[0]);
    return RT_EOK;
}
MSH_CMD_EXPORT(dbg_io_info, 获取io信息);

